home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / szadb1_4.zoo / src / stepping.c < prev    next >
C/C++ Source or Header  |  1990-11-13  |  17KB  |  621 lines

  1. /* Copyright (c) 1990 by Sozobon, Limited.  Authors: Anthony Howe,
  2.  *                             Michal Jaegermann
  3.  *
  4.  * Permission is granted to anyone to use this software for any purpose
  5.  * on any computer system, and to redistribute it freely, with the
  6.  * following restrictions:
  7.  * 1) No charge may be made other than reasonable charges for reproduction.
  8.  * 2) Modified versions must be clearly marked as such.
  9.  * 3) The authors are not responsible for any harmful consequences
  10.  *    of using this software, even if they result from defects in it.
  11.  *
  12.  * Source code in this file consist of additons and modifications
  13.  * to an original szadb code by Johann Ruegg and Don Dugger and is
  14.  * an integral part of expanded version of szadb debugger.
  15.  *
  16.  *    stepping.c        68000 Trace & Break Point Functions
  17.  *        23 Mar 90    ACH
  18.  *          1 Apr 90       MJ
  19.  *                added temporary breakpoints
  20.  *                    separated next and jump accross branch
  21.  *                     added new instructions to skip
  22.  *                    added counts on breakpoints
  23.  *                    changed way in which return address is found
  24.  *                    set hooks for executing instructions on
  25.  *                    breakpoints
  26.  *              13 Nov 90       MJ
  27.  *                              modified code which searches for a function
  28.  *                              return address in order to marry an original
  29.  *                              method from prstack and ACH heuristic approach
  30.  */
  31.  
  32.  
  33. #include <stddef.h>
  34. #include <setjmp.h>
  35. #include "adb.h"
  36. #define IN_STEPPING
  37. #include "lang.h"
  38.  
  39. extern long     bcount;
  40. extern int      lastc;
  41. extern int      lb_cur, lb_fill;
  42. extern jmp_buf  cont_buf;
  43.  
  44. #define BPT        0x4afc    /* illegal op */
  45. #define BP_VALID    1
  46. #define BP_ACTIVE    2
  47.  
  48. /*** not used
  49. #define JSR        0047200
  50. #define JMP        0047300
  51.   ** #define EA_MASK        0177700     ***//* mask out effective  address */
  52.  
  53. typedef struct {
  54.     short          *addr;
  55.     short           instr;
  56.     union {
  57.     char           *tmp_cmd[3];
  58.     struct {
  59.         long            count;
  60.         long            o_cnt;
  61.         char           *cmdline;
  62.     }               user;
  63.     }               request;
  64.     int             flag;
  65. }               break_point;
  66.  
  67. /*  various storage for stepping commands */
  68.  
  69. static char     bpstat[3] = {SILENT, SILENT, ON};
  70. static char     stp_req[3][LINESZ + 2];
  71. static char     findcmds[] = "=\"returns \";<d0=Xrr;<d0=p\n";
  72. int             print_regs;
  73.  
  74. /*
  75.  * The first position on the following list is used only for temporary
  76.  * breakpoints and is not available to a user.
  77.  */
  78. /*
  79.  * Initialize explicitely T_BPT - other are set to 0 by default.
  80.  * This union initialization is NOT portable, but Sozobon C accepts it.
  81.  */
  82. static break_point bpt_list[MAXBPTS + 1] = {
  83.            {(short *) 0, (short) 0, stp_req[0], stp_req[1], findcmds, 0}
  84. };
  85. #define T_BPT        bpt_list[0]
  86.  
  87. extern char   **bpt_cmds;
  88.  
  89.  
  90. static break_point *
  91. free_bpt (addr)
  92.     short          *addr;
  93. /*
  94.  * Find a free slot on a list of user breakpoints
  95.  */
  96. {
  97.     break_point    *bp = &bpt_list[1];
  98.     break_point    *last = &bpt_list[MAXBPTS + 1];
  99.  
  100.     for (; bp < last; bp++)
  101.     if ((bp->flag & BP_VALID) == 0 || bp->addr == addr)
  102.         return (bp);
  103.  
  104.     return (NULL);
  105. }                /* free_bpt */
  106.  
  107.  
  108. static break_point *
  109. find_bpt (addr)
  110.     short          *addr;
  111. /*
  112.  * Find if a user breakpoint is set at a given address
  113.  */
  114. {
  115.     break_point    *bp = &bpt_list[1];
  116.     break_point    *last = &bpt_list[MAXBPTS + 1];
  117.  
  118.     for (; bp < last; bp++)
  119.     if (bp->flag & BP_VALID && bp->addr == addr)
  120.         return (bp);
  121.  
  122.     return (NULL);
  123. }                /* find_bpt */
  124.  
  125. static char    *
  126. find_bcmd (bp, kind)
  127.     break_point    *bp;
  128.     int             kind;
  129. /*
  130.  * Return an address of a buffer with commands which should be
  131.  * executed for a given breakpoint or NULL
  132.  */
  133. {
  134.     char           *cmds;
  135.     int             stat;
  136.  
  137.     if (CM_CONT == kind) {
  138.     if (NULL != (cmds = bp->request.user.cmdline)) {
  139.         if (ON != *cmds++)
  140.         cmds = NULL;
  141.     }
  142.     }
  143.     else {            /* temporary breakpoint set by a stepping
  144.                  * command */
  145.     cmds = NULL;
  146.     if (SILENT != (stat = bpstat[--kind])) {
  147.         for (;;) {
  148.         if (ON == stat || (0 == kind && SILENT != stat)) {
  149.             cmds = T_BPT.request.tmp_cmd[kind];
  150.             break;
  151.         }
  152.         if (0 == kind)
  153.             break;
  154.         stat = bpstat[--kind];
  155.         }
  156.     }
  157.     }
  158.     return (cmds);
  159. }
  160.  
  161. static void
  162. exec_break (bp, kind)
  163.     break_point    *bp;
  164.     int             kind;
  165. /*
  166.  * Execute commands associated with a given breakpoint
  167.  */
  168. {
  169.     extern registers regs[];
  170.     extern long     dot;
  171.  
  172.     if (CM_CONT == kind) {
  173.     if (NULL != bp) {
  174.         if (bp->request.user.count) {
  175.         --(bp->request.user.count);
  176.         longjmp (cont_buf, 1);
  177.         }
  178.         else {
  179.         bp->request.user.count = bp->request.user.o_cnt;
  180.         dot = (long) bp->addr;
  181.         src_line (find_bcmd (bp, kind));
  182.         prtf (BREAK_AT, bp->addr);
  183.         }
  184.     }
  185.     }
  186.     else {            /* CM_STEP, CM_NEXT, CM_FINISH */
  187.     dot = *regs[PC].value;
  188.     src_line (find_bcmd ((break_point *) NULL, kind));
  189.     }
  190.  
  191.     if (print_regs)
  192.     prregs ();
  193.     prbpt (dot = *regs[PC].value);
  194.     putchr ('\n');
  195.     return;
  196. }
  197.  
  198. static void
  199. check_break (kind)
  200.     int             kind;
  201. /*
  202.  * Kind indicates which stepping command caused break.
  203.  * Not used for traps of other kind.
  204.  */
  205. {
  206.     extern int      lasttrap;
  207.     extern registers regs[];
  208.     extern char    *tnm[];
  209.     void            exec_break ();
  210.  
  211.     switch (lasttrap) {
  212.     case 2:
  213.     case 3:            /* bus & address errors */
  214.     prbuserr ();
  215.     break;
  216.     case 9:
  217.     exec_break (&T_BPT, kind);
  218.     break;            /* trace */
  219.     case 10:
  220.     prt (PROCESS_EXIT);
  221.     seeerr ();
  222.     exit (0);
  223.     case 4:            /* illegal instruction -- breakpoint */
  224.  
  225.     /*
  226.      * Give priority to temporary breakpoints set by stepping commands.
  227.      * One may reprocess if first condition fires but we are going to
  228.      * miss breakpoint anyway if walked through by :n(ext) which reverted
  229.      * to :s(tep), so let be consistent.
  230.      */
  231.     if ((T_BPT.flag & BP_VALID) &&
  232.         (T_BPT.addr == (short *) (*regs[PC].value))) {
  233.         exec_break (&T_BPT, kind);
  234.     }
  235.     else {
  236.         exec_break (find_bpt ((short *) (*regs[PC].value)), kind);
  237.     }            /* if */
  238.     break;
  239.     default:
  240.     prtf ("trap: %s\n", tnm[lasttrap]);
  241.     }                /* switch */
  242. }                /* check_break */
  243.  
  244.  
  245. static void
  246. bpts_on ()
  247. /*
  248.  *    Turn on all the break points, user and temporary,
  249.  *    before full speed execution. First go through user
  250.  *      breakpoints.  If T_BPT is on the same location as
  251.  *      a user breakpoint, then the second breakpoint turned
  252.  *      on will get BPT (invalid) instruction stored in it.
  253.  *      Turn off in a reverse order!
  254.  */
  255. {
  256.     int             i = MAXBPTS;
  257.     break_point    *bp = &bpt_list[1];
  258.     extern long     getn ();
  259.  
  260.  
  261.     for (;;) {
  262.     if (bp->flag & BP_VALID) {
  263.         bp->flag |= BP_ACTIVE;
  264.         bp->instr = (short) getn (bp->addr, 2);
  265.         putn ((long) BPT, bp->addr, 2);
  266.     }            /* if */
  267.     if (bp == &T_BPT)
  268.         break;
  269.     if (--i)
  270.         bp++;
  271.     else
  272.         bp = &T_BPT;
  273.     }                /* for */
  274. }                /* bpts_on */
  275.  
  276.  
  277. static void
  278. bpts_off ()
  279. /*
  280.  *    Turn off all the break points after full speed execution.
  281.  *    This restores the instructions so that they can be viewed normally.
  282.  *      Temporary breakpoint has to be turned off before user breakpoints.
  283.  *      Ordering is critical - otherwise you may got BPT (invalid)
  284.  *      instructions sprinkled over your code
  285.  */
  286. {
  287.     break_point    *bp = &bpt_list[0];
  288.     break_point    *last = &bpt_list[MAXBPTS + 1];
  289.  
  290.     do {
  291.     if (bp->flag & BP_ACTIVE) {
  292.         bp->flag &= ~BP_ACTIVE;
  293.         putn ((long) bp->instr, bp->addr, 2);
  294.     }            /* if */
  295.     bp++;
  296.     } while (bp < last);
  297. }                /* bpts_off */
  298.  
  299.  
  300. int
  301. MakeReq (kind)
  302.     short           kind;
  303. /*
  304.  * Handle request line for stepping commands.
  305.  * Return 0 if there was no requests on a command line and non-zero otherwise.
  306.  */
  307. {
  308.     int             idx = kind - 1;
  309.     int             status;
  310.     extern int      getrequs ();
  311.  
  312.     if (BLANK == (status = getrequs (stp_req[idx]))) {
  313.     return 0;
  314.     }
  315.  
  316.     if (REVERT == status) {
  317.     if (CM_FINISH != kind) {
  318.         status